using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using Danser_Control.Exceptions;
using Danser_Entity.Utils;
using Danser_Entity.Queries.Data;
using Danser_Entity.Queries.Filters;

namespace Danser_AJAXEnabledWebApplication.User_Controls
{
    /// <summary>
    /// Tool to build conditions as part of conditional expression, which can be used in SQL queries
    /// </summary>
    public partial class ExpressionBuilder : System.Web.UI.UserControl
    {
        #region Members:

        /// <summary>
        /// holds the data stored in session
        /// </summary>
        private IList<Condition> _conditions = null;

        /// <summary>
        /// Initial hidden condition to be referenced in each expression built by this control
        /// </summary>
        private Condition _initialCondition = null;

        /// <summary>
        /// The data source which the grid is bound to. Exists per session
        /// </summary>
        private DataTable _dataSourceTable = null;

        #endregion

        #region Constants:

        //Session keys
        private readonly String DATA_SOURCE_TABLE_KEY = "DataTable";
        private String DATA_SOURCE_TABLE_UNIQUE;

        private readonly String CONDITIONS_KEY = "Conditions";
        private String CONDITIONS_UNIQUE;

        private readonly String INITIAL_CONDITION_KEY = "InitialCondition";
        private String INITIAL_CONDITION_UNIQUE;

        private readonly String SELECTED_TABLES_KEY = "SelectedGroups";
        private String SELECTED_TABLES_UNIQUE;

        //grid components 
        private readonly String ID_LABEL_ID = "IDLabel";
        private readonly String BOOLEAN_OP_LABEL_ID = "booleanOperatorLabel";
        private readonly String NOT_CHECKBOX_ID = "notCheckBox";
        private readonly String GROUPS_LIST_ID = "groupDropDownList";
        private readonly String FIELDS_LIST_ID = "fieldDropDownList";
        private readonly String OPERATORS_LIST_ID = "operatorDropDownList";
        private readonly String VALUE_BOX_ID = "valueTextBox";
        private readonly String DELETE_BUTTON_ID = "deleteButton";

        //for regular expressions:
        private static readonly String SPECIAL_STRING_OPERATORS =
            ComparingOperators.STARTS_WITH  + "|" +
            ComparingOperators.CONTAINS     + "|" +
            ComparingOperators.ENDS_WITH;

        private static readonly String STRING_OPERATORS =
            ComparingOperators.EQUALS       + "|" +
            ComparingOperators.NOT_EQUALS   + "|" +
            SPECIAL_STRING_OPERATORS;
        
        private readonly String BOOLEAN_OPERATORS = "^EQUALS$";

        //template strings
        private readonly String DATE_FIELD = DBConstants.TEST_INFO_DATE;//"Date";
        private const String DATE_SEPARATOR_CHAR = ".";
        private readonly String DATE_TEMPLATE = "DD" + DATE_SEPARATOR_CHAR + "MM" + DATE_SEPARATOR_CHAR + "YYYY";
        private readonly String TIME_FIELD = DBConstants.TEST_INFO_TIME;//"Time";
        private const String TIME_SEPARATOR_CHAR = "-";
        private readonly String TIME_TEMPLATE = "HH" + TIME_SEPARATOR_CHAR + "MM";

        #endregion

        #region Page Load:

        /// <summary>
        /// loads the page...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            DATA_SOURCE_TABLE_UNIQUE = ClientID + DATA_SOURCE_TABLE_KEY;
            CONDITIONS_UNIQUE = ClientID + CONDITIONS_KEY;
            INITIAL_CONDITION_UNIQUE = ClientID + INITIAL_CONDITION_KEY;
            SELECTED_TABLES_UNIQUE = ClientID + SELECTED_TABLES_KEY;

            if (!IsPostBack) //first time
            {
                //initiate unique session keys
                _conditions = new List<Condition>();
                Session[CONDITIONS_UNIQUE] = _conditions;
                Session[DATA_SOURCE_TABLE_UNIQUE] = initiateTable();
                
                ClearDataSource();

                InitiateDataSource();
            }

        }

        #endregion

        #region Public API:

        /// <summary>
        /// Define the expression builder's mode of display 
        /// </summary>
        /// <param name="mode">the selected mode</param>
        public void setBuilderMode(BuilderModes mode)
        {
            switch (mode)
            {
                case BuilderModes.BUILD_FILTER: //default
                    break;
                case BuilderModes.BUILD_QUERY:
                    generationPanel.Visible = false;
                    break;
            }
        }

        /// <summary>
        /// Return the rule string generted by this control
        /// </summary>
        /// <returns></returns>
        public String getRuleString()
        {
            return ruleTextBox.Text;
        }

        public IList<Condition> getConditions(bool includeInitial)
        {
            return getConditions(includeInitial, true);
        }

        /// <summary>
        /// Retrieve all conditions added so far in the UI
        /// </summary>
        /// <returns>list of conditions</returns>
        public IList<Condition> getConditions(bool includeInitial, bool validationEnabled)
        {
            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;

            //update list
            if (_conditions == null)
                _conditions = new List<Condition>(new Condition[GridView1.Rows.Count]);

            refreshConditionList(_conditions);

            //create new list to return
            IList<Condition> returnedConditions =
                _conditions != null ?
                new List<Condition>(_conditions) :
                new List<Condition>() ;

            try
            {
                if (returnedConditions.Count > 0)
                {
                    CheckValidValue(returnedConditions[returnedConditions.Count - 1]);

                    //hide error messages from last adding
                    parserErrorLabel.Visible = false;
                    parserErrorImage.Visible = false;
                    generateRuleButton.Enabled = true;
                }
            }
            catch (DanserParserException parserException)
            {
                //notify the error only if requested
                if (validationEnabled)
                {
                    parserErrorLabel.Visible = true;
                    parserErrorImage.Visible = true;
                    parserErrorLabel.Text = parserException.Message;
                    return null;
                }
                //else ignore the invalid condition
                returnedConditions.RemoveAt(returnedConditions.Count - 1);
            }

            if (includeInitial) //add the initial
            {
                //add initial condition
                _initialCondition = Session[INITIAL_CONDITION_UNIQUE] as Condition;

                if (_initialCondition != null)
                    returnedConditions.Add(_initialCondition);
            }

            return (returnedConditions.Count > 0 ? returnedConditions : null);
        }

        /// <summary>
        /// Displays in UI format the selected rule as a list of conditions
        /// </summary>
        /// <param name="ruleToDisplay"></param>
        public void DisplayRule(RuleExpression ruleToDisplay)
        {
            if (ruleToDisplay == null) //nothing to display
                return;

            ClearDataSource();
            _conditions = ruleToDisplay.Conditions;
            
            //add rows to dataTable
            for (int i = 0; i < _conditions.Count; i++)
            {
                _dataSourceTable.Rows.Add(_dataSourceTable.NewRow());
            }
            //update session attributes
            Session[CONDITIONS_UNIQUE] = _conditions;
            Session[DATA_SOURCE_TABLE_UNIQUE] = _dataSourceTable;

            //display data on grid
            GridView1.DataSource = _dataSourceTable.DefaultView;
            GridView1.DataBind();

            //first condition doesn't have boolean operator or remove button
            GridView1.Rows[0].FindControl(BOOLEAN_OP_LABEL_ID).Visible = false;
            GridView1.Rows[0].FindControl(DELETE_BUTTON_ID).Visible = false;

            ruleTextBox.Text = ruleToDisplay.ConditionsToString(false);
        }

        /// <summary>
        /// Displays in UI format the selected ruleString as a list of conditions
        /// </summary>
        /// <param name="ruleString"></param>
        public void DisplayRule(String ruleString)
        {
            RuleExpression parsedRule = RuleExpression.ParseRuleFromString(ruleString);
            
            DisplayRule(parsedRule);
        }

        /// <summary>
        /// Set the tables to for the query expression
        /// </summary>
        /// <param name="groups"></param>
        public void setSearchingTables(Groups[] groups)
        {
            Session[SELECTED_TABLES_UNIQUE] = groups;

            ClearDataSource();

            InitiateDataSource();
        }

        /// <summary>
        /// Clear all elements defined in the control
        /// </summary>
        public void ClearRule()
        {
            ClearDataSource();
            
            //re initiate:
            InitiateDataSource();
        }

        /// <summary>
        /// Set initial condition required for building the expression
        /// </summary>
        /// <param name="initial">the initial condition to set</param>
        public void SetInitialCondition(Condition initial)
        {
            Session[INITIAL_CONDITION_UNIQUE] = initial;
        }

        #endregion

        #region Boolean Operator Selection:

        protected void ORSelector_CheckedChanged(object sender, EventArgs e)
        {
            //keep radio efect
            ANDSelector.Checked = !ORSelector.Checked;

            RefreshBooleanSelection();

        }

        protected void ANDSelector_CheckedChanged(object sender, EventArgs e)
        {
            //keep radio efect
            ORSelector.Checked = !ANDSelector.Checked;

            RefreshBooleanSelection();
           
        }

        #endregion

        #region Add/Remove Conditions and Generate Rule:

        /// <summary>
        /// Adds a new row to the conditions list. Also make sure that the data retrieved from the UI so far is saved
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void addButton_Click(object sender, EventArgs e)
        {
            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;
            _dataSourceTable = Session[DATA_SOURCE_TABLE_UNIQUE] as DataTable;

            //First - update datasource with new changes if any
            refreshConditionList(_conditions);

            //check for parsing errors in the last added condition
            Condition lastAddedCondition = _conditions[_conditions.Count - 1];
            try
            {
                CheckValidValue(lastAddedCondition);
                
                //hide error messages from last adding
                parserErrorLabel.Visible = false;
                parserErrorImage.Visible = false;
                generateRuleButton.Enabled = true;
            }
            catch(DanserParserException parserException)
            {
                parserErrorLabel.Visible = true;
                parserErrorImage.Visible = true; ;
                parserErrorLabel.Text = parserException.Message;
                return;
            }

            _dataSourceTable.Rows.Add(_dataSourceTable.NewRow());
            _conditions.Add(new Condition());

            GridView1.DataSource = _dataSourceTable;
            GridView1.DataBind();

            if (GridView1.Rows.Count > 0)
            {
                GridView1.Rows[0].FindControl(BOOLEAN_OP_LABEL_ID).Visible = false;
            }

        }

        /// <summary>
        /// handles the event of clear button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void clearButton_Click(object sender, EventArgs e)
        {
            //hide error messages from last adding
            parserErrorLabel.Visible = false;
            parserErrorImage.Visible = false;
            generateRuleButton.Enabled = true;

            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;

            //boolean operator back to default
            ANDSelector.Checked = true;
            ORSelector.Checked = !ANDSelector.Checked;

            //clear all data
            ClearDataSource();

            //re initiate:
            InitiateDataSource();

        }

        /// <summary>
        /// handles the event of generate button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void generateRuleButton_Click(object sender, EventArgs e)
        {
            //hide error messages from last adding
            parserErrorLabel.Visible = false;
            parserErrorImage.Visible = false;

            //get the conditions generated by the expression builder
            IList<Condition> conditions = getConditions(true);

            if (conditions == null)
                return;

            //build a rule out of the conditions
            RuleExpression parsedRule = new RuleExpression(conditions);

            ruleTextBox.Text = parsedRule.ConditionsToString(false);
        }

        #endregion

        #region Row Data Handlers:

        /// <summary>
        /// Called whenever the grid performes data binding. Each row will display the accordingly data saved before
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {

                //initiate lists
                Label booleanOpLabel = e.Row.FindControl(BOOLEAN_OP_LABEL_ID) as Label;
                booleanOpLabel.Visible = e.Row.RowIndex > 0 ? true : false;

                booleanOpLabel.Text = 
                    ANDSelector.Checked ? 
                    BooleanOperators.AND.ToString() : 
                    BooleanOperators.OR.ToString();

                DropDownList groupList = e.Row.FindControl(GROUPS_LIST_ID) as DropDownList;
                
                Groups[] searchTables = Session[SELECTED_TABLES_UNIQUE] as Groups[];
                if (searchTables == null)
                    searchTables = new Groups[] { Groups.Information };
                
                BindListToEnum(groupList, searchTables);

                //display default table's fields
                DropDownList fieldList = e.Row.FindControl(FIELDS_LIST_ID) as DropDownList;
                BindDefaultFieldsList(fieldList, searchTables[0]);

                DropDownList operatorDropDownList = e.Row.FindControl(OPERATORS_LIST_ID) as DropDownList;
                BindListToEnum(operatorDropDownList, new ComparingOperators());

                //bind saved parameters:
                _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;
                if (e.Row.RowIndex >= 0 && e.Row.RowIndex < _conditions.Count)
                {

                    Condition current = _conditions[e.Row.RowIndex];

                    ((Label)e.Row.FindControl(ID_LABEL_ID)).Text = "(" + e.Row.RowIndex + ")";

                    ((CheckBox)e.Row.FindControl(NOT_CHECKBOX_ID)).Checked = current.Not ? true : false;

                    groupList.SelectedValue = current.Group.ToString();

                    switch (current.Group)
                    {
                        case Groups.Information: //default
                            break;
                        case Groups.Parameters:
                            BindListToEnum(fieldList, new TestParamsFields());
                            break;
                        case Groups.Results:
                            BindListToEnum(fieldList, new TestResultsFields());
                            break;
                        case Groups.Users:
                            BindListToEnum(fieldList, new UsersFields());
                            break;
                        case Groups.ValidationTemplates:
                            BindListToEnum(fieldList, new ValidationTemplatesFields());
                            break;
                    }
                    fieldList.SelectedValue = current.Field;
                    //Match operators to default field
                    MatchOperators(fieldList.SelectedValue, operatorDropDownList);

                    operatorDropDownList.SelectedValue = current.Operator.ToString();
                    ((TextBox)e.Row.FindControl(VALUE_BOX_ID)).Text = current.Value;
                }
            }
        }

        /// <summary>
        /// handles the event of delete button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void deleteButton_Click(object sender, EventArgs e)
        {
            //hide error messages from last adding
            parserErrorLabel.Visible = false;
            parserErrorImage.Visible = false;
            generateRuleButton.Enabled = true;

            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;
            _dataSourceTable = Session[DATA_SOURCE_TABLE_UNIQUE] as DataTable;

            //update the session with data entered from user
            refreshConditionList(_conditions);

            LinkButton deleteButton = sender as LinkButton;

            GridViewRow toDeleteRow = (deleteButton.Parent.Parent) as GridViewRow;

            _conditions.RemoveAt(toDeleteRow.RowIndex);
            _dataSourceTable.Rows.RemoveAt(toDeleteRow.RowIndex);
            
            GridView1.DataSource = _dataSourceTable;
            GridView1.DataBind();

            if (toDeleteRow.RowIndex == 0) //first was deleted
            {
                _conditions[0].IsFirst = true;
            }
            //do not allow the page to be left out of lines
            if (GridView1.Rows.Count == 1)
            {
                GridView1.Rows[0].FindControl(DELETE_BUTTON_ID).Visible = false;
            }

        }

        /// <summary>
        /// Refreshe the Field list according to the selected Group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void groupDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            DropDownList groupList = sender as DropDownList;

            GridViewRow row = (groupList.Parent.Parent) as GridViewRow;

            DropDownList fieldList = row.FindControl(FIELDS_LIST_ID) as DropDownList;

            DropDownList operatorList = row.FindControl(OPERATORS_LIST_ID) as DropDownList;          

            Groups group = (Groups)Enum.Parse(typeof(Groups), groupList.SelectedValue);
            MatchFieldElements(group, fieldList);

            MatchOperators(fieldList.SelectedValue, operatorList);
        }

        /// <summary>
        /// Refreshe the field operator list with the relevant operators according to the selected field's type (text or number)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void fieldDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            DropDownList fieldList = sender as DropDownList;

            GridViewRow row = (fieldList.Parent.Parent) as GridViewRow;

            DropDownList operatorsList = row.FindControl(OPERATORS_LIST_ID) as DropDownList;

            TextBox inputData = row.FindControl(VALUE_BOX_ID) as TextBox;

            String field = fieldList.SelectedValue;

            //check for the type of the field
            MatchOperators(field, operatorsList);

            //if necessary, add template to text box
            MatchInputTemplate(field, inputData);

        }

        #endregion

        #region Helpers:

        /// <summary>
        /// Update conditions list with new selected boolean operator
        /// </summary>
        private void RefreshBooleanSelection()
        {
            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;
            _dataSourceTable = Session[DATA_SOURCE_TABLE_UNIQUE] as DataTable;

            //First - update datasource with new changes if any
            refreshConditionList(_conditions);

            InitialGridTableBinding(_dataSourceTable);
        }

        /// <summary>
        /// Checks for correct value format according to the field type definitions
        /// </summary>
        /// <param name="lastAddedCondition">the condition to check</param>
        /// <exception cref="DanserParserException">in case of invalid input</exception>
        private void CheckValidValue(Condition lastAddedCondition)
        {
            //field of type boolean
            if (Utils.IsFieldTypBoolean(lastAddedCondition.Field))
            {
                string normalizedValue = lastAddedCondition.Value.ToLower();
                if (!normalizedValue.Equals("true") && !normalizedValue.Equals("false"))
                {
                    throw new DanserParserException(String.Format(ErrorMessages.RuleParserBoolean));
                }
            }
            //field of type string
            else if (Utils.IsFieldTypeString(lastAddedCondition.Field))
            {
                if (!Utils.IsOperatorMatch(SPECIAL_STRING_OPERATORS, lastAddedCondition.Operator.ToString()) &&
                         String.IsNullOrEmpty(lastAddedCondition.Value))

                    throw new DanserParserException(String.Format(ErrorMessages.RuleParserString));
            }
            //field of type string in date format
            else if (lastAddedCondition.Field.Equals(DATE_FIELD))
            {
                String[] dateElements = lastAddedCondition.Value.Split(new String[] { DATE_SEPARATOR_CHAR }, StringSplitOptions.RemoveEmptyEntries);
                if (dateElements.Length != 3)
                    throw new DanserParserException(
                        String.Format(ErrorMessages.RuleParserTimeDate, new Object[] { DATE_TEMPLATE }));
            }
            //field of type string in time format
            else if (lastAddedCondition.Field.Equals(TIME_FIELD))
            {
                String[] timeElements = lastAddedCondition.Value.Split(new String[] { TIME_SEPARATOR_CHAR }, StringSplitOptions.RemoveEmptyEntries);
                if (timeElements.Length != 2)
                    throw new DanserParserException(
                        String.Format(ErrorMessages.RuleParserTimeDate, new Object[] { TIME_TEMPLATE }));
            }
            //else - not string, bool or time/date => numeric
            else
            {
                try
                {
                    //also includes integer
                    Convert.ToDouble(lastAddedCondition.Value);
                }
                catch (Exception invalidFormatOrOverflowException)
                {
                    throw new DanserParserException(String.Format(ErrorMessages.RuelParserNum));
                }
            }
        }

        /// <summary>
        /// Initiate the data sources - one single initial row
        /// </summary>
        private void InitiateDataSource()
        {
            _dataSourceTable = Session[DATA_SOURCE_TABLE_UNIQUE] as DataTable;
            
            if (_conditions != null)
                _conditions.Add(new Condition());

            if (_dataSourceTable != null)
            {
                _dataSourceTable.Rows.Add(_dataSourceTable.NewRow());
                InitialGridTableBinding(_dataSourceTable);
            }


        }

        /// <summary>
        /// Binds the grid to data table for the first time
        /// </summary>
        /// <param name="dataTable"></param>
        private void InitialGridTableBinding(DataTable dataTable)
        {
            GridView1.DataSource = dataTable;
            GridView1.DataBind();

            GridView1.Rows[0].FindControl(DELETE_BUTTON_ID).Visible = false;
            GridView1.Rows[0].FindControl(BOOLEAN_OP_LABEL_ID).Visible = false;
        }

        /// <summary>
        /// Clears all the Data stored
        /// </summary>
        private void ClearDataSource()
        {
            _conditions = Session[CONDITIONS_UNIQUE] as IList<Condition>;
            _dataSourceTable = Session[DATA_SOURCE_TABLE_UNIQUE] as DataTable;
            
            //clear list
            if (_conditions != null)
                _conditions.Clear();
            
            //clear grid
            if (_dataSourceTable != null)
                _dataSourceTable.Clear();

            //clear rule pane
            ruleTextBox.Text = "";
        }

        /// <summary>
        /// Updates the conditions list with the appropriate data recieved in the UI
        /// </summary>
        /// <param name="conditions"></param>
        private void refreshConditionList(IList<Condition> conditions)
        {
            for (int i = 0; i < GridView1.Rows.Count; i++)
            {
                GridViewRow row = GridView1.Rows[i];

                BooleanOperators boolOperator = 0;
                bool isNot = false;
                Groups group = 0;
                String field = null;
                ComparingOperators qOperator = 0;
                String value;

                //extract data
                if (i != 0) //skip for first row
                {
                    boolOperator = 
                        ANDSelector.Checked ? 
                        BooleanOperators.AND :
                        BooleanOperators.OR;
                }
                CheckBox notCheckBox = row.FindControl(NOT_CHECKBOX_ID) as CheckBox;
                isNot = notCheckBox.Checked;

                DropDownList groupDropDownList = row.FindControl(GROUPS_LIST_ID) as DropDownList;
                group = (Groups)Enum.Parse(typeof(Groups), groupDropDownList.SelectedValue);

                DropDownList fieldDropDownList = row.FindControl(FIELDS_LIST_ID) as DropDownList;

                switch (group)
                {
                    case Groups.Information:
                        TestInfoFields infoField = (TestInfoFields)Enum.Parse(typeof(TestInfoFields), fieldDropDownList.SelectedValue);
                        field = infoField.ToString();
                        break;

                    case Groups.Parameters:
                        TestParamsFields paramField = (TestParamsFields)Enum.Parse(typeof(TestParamsFields), fieldDropDownList.SelectedValue);
                        field = paramField.ToString();
                        break;

                    case Groups.Results:
                        TestResultsFields resultField = (TestResultsFields)Enum.Parse(typeof(TestResultsFields), fieldDropDownList.SelectedValue);
                        field = resultField.ToString();
                        break;
                    case Groups.Users:
                        UsersFields userField = (UsersFields)Enum.Parse(typeof(UsersFields), fieldDropDownList.SelectedValue);
                        field = userField.ToString();
                        break;
                    case Groups.ValidationTemplates:
                        ValidationTemplatesFields validationField = (ValidationTemplatesFields)Enum.Parse(typeof(ValidationTemplatesFields), fieldDropDownList.SelectedValue);
                        field = validationField.ToString();
                        break;
                }

                DropDownList operatorDropDownList = row.FindControl(OPERATORS_LIST_ID) as DropDownList;
                qOperator = (ComparingOperators)Enum.Parse(typeof(ComparingOperators), operatorDropDownList.SelectedValue);

                TextBox valueTextBox = row.FindControl(VALUE_BOX_ID) as TextBox;
                value = valueTextBox.Text;

                //create the condition:
                Condition cond = new Condition();
                cond.Group = group;
                cond.Field = field;
                cond.Operator = qOperator;
                cond.Value = value;
                cond.BoolOperator = boolOperator;
                cond.Not = isNot;
                cond.IsFirst = i == 0 ? true : false;

                //update to list
                conditions[i] = cond;

            }
        }

        /// <summary>
        /// Binds a DropDownList's to a selected Enumeration type
        /// </summary>
        /// <param name="list">The list to bind to values</param>
        /// <param name="enumType">The enum type to bind the list to</param>
        private void BindListToEnum(DropDownList list, Enum enumType)
        {
            String[] selectedItems = Enum.GetNames(enumType.GetType());
            BindListToStrings(list, selectedItems);
        }

        /// <summary>
        /// Binds a DropDownList's to a selected DB tables
        /// </summary>
        /// <param name="list">The list to bind to values</param>
        /// <param name="items">Array of tables to bind the list to</param>
        private void BindListToEnum(DropDownList list, Groups[] items)
        {
            String[] selectedItems = new String[items.Length];
            for (int i = 0; i < items.Length; i++)
            {
                selectedItems[i] = items[i].ToString();
            }

            BindListToStrings(list, selectedItems);
        }

        /// <summary>
        /// Binds a DropDownList's to a selected DB tables
        /// </summary>
        /// <param name="list">The list to bind to values</param>
        /// <param name="items">Array of tables to bind the list to given in string format</param>
        private void BindListToStrings(DropDownList list, String[] items)
        {
            list.DataSource = items;
            list.DataBind();
        }

        /// <summary>
        /// Binds DropDownList's to a selected fields list according to given DB table
        /// </summary>
        /// <param name="fieldsList">The list to bind to values</param>
        /// <param name="tableName">the name of table which ownes the fields to bind </param>
        private void BindDefaultFieldsList(DropDownList fieldsList, Groups tableName)
        {
            switch (tableName)
            {
                case Groups.Information:
                    BindListToEnum(fieldsList, new TestInfoFields());
                    break;
                case Groups.Parameters:
                    BindListToEnum(fieldsList, new TestParamsFields());
                    break;
                case Groups.Results:
                    BindListToEnum(fieldsList, new TestResultsFields());
                    break;
                case Groups.Users:
                    BindListToEnum(fieldsList, new UsersFields());
                    break;
                case Groups.ValidationTemplates:
                    BindListToEnum(fieldsList, new ValidationTemplatesFields());
                    break;
            }
        }
        /// <summary>
        /// Select to display in the Field list all relevant fields from the selected group
        /// </summary>
        /// <param name="group">list to extract the selected group</param>
        /// <param name="fieldList"></param>
        private void MatchFieldElements(Groups group, DropDownList fieldList)
        {
            switch (group)
            {
                case Groups.Information:
                    BindListToEnum(fieldList, new TestInfoFields());
                    break;

                case Groups.Parameters:
                    BindListToEnum(fieldList, new TestParamsFields());
                    break;

                case Groups.Results:
                    BindListToEnum(fieldList, new TestResultsFields());
                    break;
                case Groups.Users:
                    BindListToEnum(fieldList, new UsersFields());
                    break;
                case Groups.ValidationTemplates:
                    BindListToEnum(fieldList, new ValidationTemplatesFields());
                    break;
            }

        }

        /// <summary>
        /// Matches the relevant operatros to the type of the selected fields
        /// </summary>
        /// <param name="field">The selected field in UI</param>
        /// <param name="operatorsList">List to bind to operator values</param>
        private void MatchOperators(String field, DropDownList operatorsList)
        {
            //check for the type of the field
            Regex stringOperators = new Regex(STRING_OPERATORS);

            Regex boolOperators = new Regex(BOOLEAN_OPERATORS);

            if (Utils.IsFieldTypeString(field)) //field type is string
            {
                //disable unnecessary operators:
                for (int i = 0; i < operatorsList.Items.Count; i++)
                {
                    operatorsList.Items[i].Enabled =
                        Utils.IsOperatorMatch(STRING_OPERATORS, operatorsList.Items[i].Value);
                }
            }
            else if (Utils.IsFieldTypBoolean(field)) //field type is bbolean
            {
                //disable unnecessary operators:
                for (int i = 0; i < operatorsList.Items.Count; i++)
                {
                    operatorsList.Items[i].Enabled =
                        Utils.IsOperatorMatch(BOOLEAN_OPERATORS, operatorsList.Items[i].Value);
                }
            }
            else //any other type
            {
                for (int i = 0; i < operatorsList.Items.Count; i++)
                {
                    operatorsList.Items[i].Enabled =
                        !Utils.IsOperatorMatch(SPECIAL_STRING_OPERATORS, operatorsList.Items[i].Value);
                }
            }
        }

        /// <summary>
        /// Match an Input template for specific field type such as Time and Date
        /// </summary>
        /// <param name="field">The field name</param>
        /// <param name="inputData">The text box which its text is to be formatted</param>
        private void MatchInputTemplate(String field, TextBox inputData)
        {
            //check for the type of the field
            Regex dateFields = new Regex(DATE_FIELD);
            Regex timeFields = new Regex(TIME_FIELD);

            inputData.Text =
                dateFields.IsMatch(field) ? //type is date
                DATE_TEMPLATE :
                    timeFields.IsMatch(field) ? //type is time
                    TIME_TEMPLATE :
                    ""; //anything else
        }

        /// <summary>
        /// Initiates the Data table for the grid
        /// </summary>
        /// <returns></returns>
        private DataTable initiateTable()
        {
            DataTable table = new DataTable();

            table.Columns.Add("id", typeof(int));

            return table;
        }

        #endregion

    }

    #region BuilderModes Enum:

    /// <summary>
    /// Define the display mode of the expression builder
    /// </summary>
    public enum BuilderModes
    {
        /// <summary>
        /// builing a query
        /// </summary>
        BUILD_QUERY,
        /// <summary>
        /// defalt mode
        /// </summary>
        BUILD_FILTER,
    }

    #endregion

}